package IO;



import java.io.IOException;
import java.util.Random;
import java.util.ArrayList;

public class Generator {
	
	private int width;
	private int heigth;
	private int numOfSpawns;
	private char[][] level;
	private Waypoint goal;
	private ArrayList<Waypoint> spawns;
	
	public Generator(int width, int heigth, int numOfSpawns, String saveLoc) throws IOException
	{
		this.width = width;
		this.heigth = heigth;
		this.level = new char[width][heigth];
		this.numOfSpawns = numOfSpawns;
		this.goal = generateGoal();
		this.spawns = generateSpawns();generatePaths();
		fillLevel();
		level generatedLevel = new level(level);
		generatedLevel.saveLevel(saveLoc);
	}
	
	public Generator(int width, int heigth, int numOfSpawns) throws IOException
	{
		this.width = width;
		this.heigth = heigth;
		this.level = new char[width][heigth];
		this.numOfSpawns = numOfSpawns;
		this.goal = generateGoal();
		this.spawns = generateSpawns();
		generatePaths();
		fillLevel();
		
	}

	private void fillLevel() {
		int x, y = 0;
		
		while(y < level[0].length)
		{
			x = 0;
			while (x < level.length)
			{
				if(level[x][y] == '\u0000')
				{
					level[x][y] = '_';
				}
				x++;
			}
			y++;
		}
		System.out.println("Level filled");
		
		for(int j = 0;j<level[0].length;j++)
		{
			for(int i=0;i<level.length;i++)
				System.out.print(level[i][j]);
			System.out.println("/n");

		}
	}

	private Waypoint generateGoal()
	{
		Waypoint goal;
		int x = 0, y = 0;
		Random rnd = new Random();
		
		x = rnd.nextInt(this.width);
		if(x == 0)
		{
			x++;
		}
		else if(x == this.width)
		{
			x--;
		}
		
		y = rnd.nextInt(this.heigth);
		if (y == 0)
		{
			y++;
		}
		else if(y == this.heigth)
		{
			y--;
		}
		this.level[x][y] = 'X';
		goal = new Waypoint(x, y);
		
		return goal;
	}
	
	private ArrayList<Waypoint> generateSpawns()
	{
		int counter = 0;
		int x = 0, y = 0;
		ArrayList<Waypoint> spawns = new ArrayList<Waypoint>();
		Random rnd = new Random();
		Waypoint potSpawn;
		
		while (counter < this.numOfSpawns)
		{
			x = rnd.nextInt(this.width - 1);
			if(x == 0)
			{
				x++;
			}
			else if(x == this.width - 1)
			{
				x--;
			}
			
			y = rnd.nextInt(this.heigth);
			if (y == 0)
			{
				y++;
			}
			else if(y == this.heigth)
			{
				y--;
			}
			
			potSpawn = new Waypoint(x, y);
			
			if(!this.goal.equals(potSpawn) && searchWP(spawns, potSpawn))
			{
				
				spawns.add(new Waypoint(x, y));
				this.level[x][y] = 'S';
				counter++;
			}
		}
		return spawns;
	}
	
	private boolean searchWP(ArrayList<Waypoint> spawns, Waypoint spawn)
	{
		int x = 0;
		int length = spawns.size();
		while(x < length)
		{
			if(spawns.get(x).getX() == spawn.getX() && spawns.get(x).getY() == spawn.getY())
			{
				return false;
			}
			else
			{
				x++;
			}
		}
		return true;
	}

	private void generatePaths() 
	{
		int x, y;
		int xDifference = 0;
		int yDifference = 0;
		int index = 0;
		Waypoint spawn;
		
		while(index < this.spawns.size())
		{
		x = 0;
		y = 0;
		spawn = this.spawns.get(index);
		
		// positve xDiff means that goal is to the left of spawn, negative that it's to the right
		// positive yDiff means that goal is above spawn, negative that it's below
		xDifference = spawn.getX() - this.goal.getX();
		yDifference = spawn.getY() - this.goal.getY();
		
		x = spawn.getX();
		y = spawn.getY();
		
		System.out.println("Goal is at: " + this.goal.getX() + "/" + this.goal.getY());
		System.out.println("Spawn is at: " + spawn.getX() + "/" + spawn.getY());
		System.out.println("xDifference: " + xDifference);
		System.out.println("yDifference: " + yDifference);
		
		if(xDifference > 0)
		{
			for(int i = 0; i < xDifference; i++)
			{
				x--;
				if(x != this.goal.getX())
				{
					this.level[x][y] = '<';
				}
				
				if(x == this.goal.getX() && yDifference > 0)
				{
					this.level[x][y] = '^';
				}
				else if (x == this.goal.getX() && yDifference < 0)
				{
					this.level[x][y] = 'v';
				}
			}
		}
		else if(xDifference < 0)
		{
			for(int i = 0; i > xDifference; i--)
			{
				x++;
				if(x != this.goal.getX())
				{
					this.level[x][y] = '>';
				}
				
				if(x == this.goal.getX() && yDifference > 0)
				{
					this.level[x][y] = '^';
				}
				else if (x == this.goal.getX() && yDifference < 0)
				{
					this.level[x][y] = 'v';
				}
			}
		}
		
		if (yDifference > 0)
		{
			for(int i = 0; i < yDifference; i++)
			{
				y--;
				if(y != this.goal.getY())
				{
					this.level[x][y] = '^';
				}
			}
		}
		else if(yDifference < 0)
		{
			for(int i = 0; i > yDifference; i--)
			{
				y++;
				if(y != this.goal.getY())
				{
					this.level[x][y] = 'v';
				}
			}
		}
		
		System.out.println("Goal is at: " + this.goal.getX() + "/" + this.goal.getY());
		System.out.println("Spawn is at: " + spawn.getX() + "/" + spawn.getY());
		index++;
		}
	}
	
	public char[][] returnLevel()
	{
		return this.level;
		
	}
	
	public String convertLevel()
	{
		return parser.toString(this.level);
	}

}
